/*
C语言实现多重继承示例

  多重继承结构：
      Animal
     /      \
  Mammal   Bird
     \      /
      Bat

  多重继承的实现：
    1. 通过结构体嵌套实现多个基类的组合
    2. 为每个基类提供独立的虚函数表
    3. 处理菱形继承问题

*/

#include <stdio.h>
#include <stdlib.h>

// 基类 Animal
typedef struct {
    void (*eat)(void*);
    void (*sleep)(void*);
    const char* name;
} Animal;


void animal_eat(void* self) {
    Animal* animal = (Animal*)self;
    printf("%s is eating\n", animal->name);
}


void animal_sleep(void* self) {
    Animal* animal = (Animal*)self;
    printf("%s is sleeping.\n", animal->name);
}


void init_animal(Animal* animal, const char* name) {
    animal->name = name;
    animal->eat = animal_eat;
    animal->sleep = animal_sleep;
}


// 基类 Mammal
typedef struct {
    void (*feed_milk)(void*);
} Mammal;


void mammal_feed_milk(void* self) {
    printf("Feeding milk...\n");
}


void init_mammal(Mammal* mammal) {
    mammal->feed_milk = mammal_feed_milk;
}


// 基类 Bird
typedef struct {
    void (*fly)(void*);
} Bird;


void bird_fly(void* self) {
    printf("Flying...\n");
}


void init_bird(Bird* bird) {
    bird->fly = bird_fly;
}


// 派生类 Bat
typedef struct {
    // 多重继承：包含多个基类
    Animal animal;
    Mammal mammal;
    Bird bird;
    int wingspan;
} Bat;


void bat_eat(void* self) {
    printf("Bat %s is eating.\n", ((Bat*)self)->animal.name);
}


void init_bat(Bat* bat, const char* name, int wingspan) {
    // 初始化各个基类部分
    init_animal(&bat->animal, name);
    init_mammal(&bat->mammal);
    init_bird(&bat->bird);

    // 重写Animal的eat方法
    bat->animal.eat = bat_eat;

    // 初始化子类特有成员
    bat->wingspan = wingspan;
}


// 类型转换函数
Animal* bat_to_animal(Bat* bat) {
    return &bat->animal;
}


// 类型转换函数
Mammal* bat_to_mammal(Bat* bat) {
    return &bat->mammal;
}


// 类型转换函数
Bird* bat_to_bird(Bat* bat) {
    return &bat->bird;
}


int main() {
    Bat bat;
    init_bat(&bat, "Batty", 100);

    // 作为Animal使用
    Animal* animal = bat_to_animal(&bat);
    animal->eat(animal);
    animal->sleep(animal);

    // 作为Mammal使用
    Mammal* mammal = bat_to_mammal(&bat);
    mammal->feed_milk(mammal);

    // 作为Bird使用
    Bird* bird = bat_to_bird(&bat);
    bird->fly(bird);

    // 直接访问Bat特有成员
    printf("Wingspan: %d\n", bat.wingspan);

    return 0;
}